دليل شامل لواجهة برمجة تطبيقات التنقل (Navigation API) لبناء تطبيقات صفحة واحدة (SPAs) حديثة وعالية الأداء مع إمكانيات توجيه متقدمة وإدارة لسجل التصفح.
إتقان واجهة برمجة تطبيقات التنقل (Navigation API): توجيه تطبيقات الصفحة الواحدة وإدارة سجل التصفح
تمثل واجهة برمجة تطبيقات التنقل (Navigation API) تقدمًا كبيرًا في كيفية تعاملنا مع التوجيه وإدارة سجل التصفح داخل تطبيقات الصفحة الواحدة (SPAs). غالبًا ما تعتمد الطرق التقليدية على التلاعب بكائن `window.location` أو استخدام مكتبات خارجية. وعلى الرغم من أن هذه الأساليب قد خدمتنا جيدًا، إلا أن واجهة برمجة تطبيقات التنقل تقدم حلاً أكثر انسيابية وأداءً وغنيًا بالميزات، مما يمنح المطورين تحكمًا أكبر في تجربة تصفح المستخدم.
ما هي واجهة برمجة تطبيقات التنقل (Navigation API)؟
واجهة برمجة تطبيقات التنقل هي واجهة برمجة تطبيقات حديثة للمتصفح مصممة لتبسيط وتعزيز الطريقة التي تدير بها تطبيقات الصفحة الواحدة التنقل والتوجيه وسجل التصفح. إنها تقدم كائنًا جديدًا هو `navigation`، يوفر طرقًا وأحداثًا تسمح للمطورين باعتراض أحداث التنقل والتحكم فيها، وتحديث عنوان URL، والحفاظ على سجل تصفح متسق دون إعادة تحميل الصفحة بالكامل. ينتج عن هذا تجربة مستخدم أسرع وأكثر سلاسة واستجابة.
فوائد استخدام واجهة برمجة تطبيقات التنقل
- تحسين الأداء: من خلال التخلص من إعادة تحميل الصفحة بالكامل، تعمل واجهة برمجة تطبيقات التنقل على تحسين أداء تطبيقات الصفحة الواحدة بشكل كبير. تصبح الانتقالات بين العروض المختلفة أسرع وأكثر سلاسة، مما يؤدي إلى تجربة مستخدم أكثر جاذبية.
- تحكم معزز: توفر الواجهة تحكمًا دقيقًا في أحداث التنقل، مما يسمح للمطورين باعتراض سلوك التنقل وتعديله حسب الحاجة. ويشمل ذلك منع التنقل، وإعادة توجيه المستخدمين، وتنفيذ منطق مخصص قبل أو بعد حدوث التنقل.
- إدارة مبسطة لسجل التصفح: أصبحت إدارة سجل التصفح في المتصفح أسهل مع واجهة برمجة تطبيقات التنقل. يمكن للمطورين إضافة إدخالات السجل واستبدالها والتنقل بينها برمجيًا، مما يضمن تجربة تصفح متسقة ويمكن التنبؤ بها.
- تنقل وصفي (Declarative): تشجع واجهة برمجة تطبيقات التنقل على نهج أكثر وصفية للتوجيه، مما يسمح للمطورين بتحديد قواعد وسلوكيات التنقل بطريقة واضحة وموجزة. هذا يحسن قابلية قراءة الكود وصيانته.
- التكامل مع أطر العمل الحديثة: تم تصميم واجهة برمجة تطبيقات التنقل للتكامل بسلاسة مع أطر عمل ومكتبات جافاسكريبت الحديثة، مثل React و Angular و Vue.js. وهذا يسمح للمطورين بالاستفادة من ميزات الواجهة ضمن مسارات عمل التطوير الحالية الخاصة بهم.
المفاهيم والميزات الأساسية
1. كائن `navigation`
جوهر واجهة برمجة تطبيقات التنقل هو كائن `navigation`، الذي يمكن الوصول إليه من خلال الكائن العام `window` (أي `window.navigation`). يوفر هذا الكائن الوصول إلى العديد من الخصائص والطرق المتعلقة بالتنقل، بما في ذلك:
- `currentEntry`: يعيد كائن `NavigationHistoryEntry` يمثل الإدخال الحالي في سجل التنقل.
- `entries()`: يعيد مصفوفة من كائنات `NavigationHistoryEntry` تمثل جميع الإدخالات في سجل التنقل.
- `navigate(url, { state, info, replace })`: ينتقل إلى عنوان URL جديد.
- `back()`: ينتقل إلى الإدخال السابق في سجل التصفح.
- `forward()`: ينتقل إلى الإدخال التالي في سجل التصفح.
- `reload()`: يعيد تحميل الصفحة الحالية.
- `addEventListener(event, listener)`: يضيف مستمعًا للأحداث المتعلقة بالتنقل.
2. `NavigationHistoryEntry`
تمثل واجهة `NavigationHistoryEntry` إدخالًا واحدًا في سجل التنقل. وهي توفر معلومات حول الإدخال، مثل عنوان URL الخاص به، وحالته، ومعرّفه الفريد.
- `url`: عنوان URL الخاص بإدخال السجل.
- `key`: معرّف فريد لإدخال السجل.
- `id`: معرّف فريد آخر، مفيد بشكل خاص لتتبع دورة حياة حدث التنقل.
- `sameDocument`: قيمة منطقية (boolean) تشير إلى ما إذا كان التنقل ينتج عنه تنقل داخل نفس المستند.
- `getState()`: يعيد الحالة المرتبطة بإدخال السجل (التي تم تعيينها أثناء التنقل).
3. أحداث التنقل
تطلق واجهة برمجة تطبيقات التنقل عدة أحداث تسمح للمطورين بمراقبة سلوك التنقل والتحكم فيه. تشمل هذه الأحداث:
- `navigate`: يتم إطلاقه عند بدء التنقل (مثل النقر على رابط، أو إرسال نموذج، أو استدعاء `navigation.navigate()`). هذا هو الحدث الأساسي لاعتراض ومعالجة طلبات التنقل.
- `navigatesuccess`: يتم إطلاقه عند اكتمال التنقل بنجاح.
- `navigateerror`: يتم إطلاقه عند فشل التنقل (على سبيل المثال، بسبب خطأ في الشبكة أو استثناء غير معالج).
- `currentchange`: يتم إطلاقه عند تغيير إدخال السجل الحالي (على سبيل المثال، عند التنقل للأمام أو للخلف).
- `dispose`: يتم إطلاقه عندما يصبح `NavigationHistoryEntry` غير قابل للوصول، كما هو الحال عند إزالته من السجل أثناء عملية `replaceState`.
تنفيذ التوجيه باستخدام واجهة برمجة تطبيقات التنقل: مثال عملي
دعنا نوضح كيفية استخدام واجهة برمجة تطبيقات التنقل لتنفيذ التوجيه الأساسي في تطبيق صفحة واحدة بسيط. لنفترض تطبيقًا بثلاثة عروض: الصفحة الرئيسية، حول، والاتصال.
أولاً، أنشئ دالة للتعامل مع تغييرات المسار:
function handleRouteChange(url) {
const contentDiv = document.getElementById('content');
switch (url) {
case '/':
contentDiv.innerHTML = 'الرئيسية
أهلاً بك في الصفحة الرئيسية!
';
break;
case '/about':
contentDiv.innerHTML = 'حول
اعرف المزيد عنا.
';
break;
case '/contact':
contentDiv.innerHTML = 'اتصل بنا
تواصل معنا.
';
break;
default:
contentDiv.innerHTML = '404 غير موجود
الصفحة غير موجودة.
';
}
}
بعد ذلك، أضف مستمعًا لحدث `navigate`:
window.navigation.addEventListener('navigate', (event) => {
const url = new URL(event.destination.url).pathname;
event.preventDefault(); // منع التنقل الافتراضي للمتصفح
const promise = new Promise((resolve) => {
handleRouteChange(url);
resolve(); // حل الوعد بعد معالجة المسار
});
event.transition = promise;
});
يعترض هذا الكود حدث `navigate`، ويستخرج عنوان URL من كائن `event.destination`، ويمنع التنقل الافتراضي للمتصفح، ويستدعي `handleRouteChange` لتحديث المحتوى، ويضبط الوعد `event.transition`. يضمن تعيين `event.transition` أن ينتظر المتصفح حتى يكتمل تحديث المحتوى قبل تحديث الصفحة بصريًا.
أخيرًا، يمكنك إنشاء روابط تؤدي إلى التنقل:
الرئيسية | حول | اتصل بنا
وأرفق مستمع نقر لهذه الروابط:
document.addEventListener('click', (event) => {
if (event.target.tagName === 'A' && event.target.hasAttribute('data-navigo')) {
event.preventDefault();
window.navigation.navigate(event.target.href);
}
});
يقوم هذا بإعداد توجيه أساسي من جانب العميل باستخدام واجهة برمجة تطبيقات التنقل. الآن، سيؤدي النقر على الروابط إلى إطلاق حدث تنقل يقوم بتحديث محتوى عنصر `div` المسمى `content` دون إعادة تحميل الصفحة بالكامل.
إضافة إدارة الحالة (State Management)
تسمح لك واجهة برمجة تطبيقات التنقل أيضًا بربط حالة بكل إدخال في سجل التصفح. هذا مفيد للحفاظ على البيانات عبر أحداث التنقل. دعنا نعدل المثال السابق ليشمل كائن حالة.
عند استدعاء `navigation.navigate()`، يمكنك تمرير كائن `state`:
window.navigation.navigate('/about', { state: { pageTitle: 'من نحن' } });
داخل مستمع حدث `navigate`، يمكنك الوصول إلى الحالة باستخدام `event.destination.getState()`:
window.navigation.addEventListener('navigate', (event) => {
const url = new URL(event.destination.url).pathname;
const state = event.destination.getState();
event.preventDefault();
const promise = new Promise((resolve) => {
handleRouteChange(url, state);
resolve();
});
event.transition = promise;
});
function handleRouteChange(url, state = {}) {
const contentDiv = document.getElementById('content');
let title = state.pageTitle || 'تطبيقي'; // عنوان افتراضي
switch (url) {
case '/':
contentDiv.innerHTML = 'الرئيسية
أهلاً بك في الصفحة الرئيسية!
';
title = 'الرئيسية';
break;
case '/about':
contentDiv.innerHTML = 'حول
اعرف المزيد عنا.
';
break;
case '/contact':
contentDiv.innerHTML = 'اتصل بنا
تواصل معنا.
';
break;
default:
contentDiv.innerHTML = '404 غير موجود
الصفحة غير موجودة.
';
title = '404 غير موجود';
}
document.title = title;
}
في هذا المثال المعدل، تقبل دالة `handleRouteChange` الآن معلمة `state` وتستخدمها لتحديث عنوان المستند. إذا لم يتم تمرير أي حالة، فإنها تستخدم القيمة الافتراضية 'تطبيقي'.
استخدام `navigation.updateCurrentEntry()`
في بعض الأحيان قد ترغب في تحديث حالة إدخال السجل الحالي دون تشغيل تنقل جديد. تسمح لك طريقة `navigation.updateCurrentEntry()` بالقيام بذلك. على سبيل المثال، إذا غير المستخدم إعدادًا في الصفحة الحالية، يمكنك تحديث الحالة لتعكس هذا التغيير:
function updateUserSetting(setting, value) {
const currentState = navigation.currentEntry.getState() || {};
const newState = { ...currentState, [setting]: value };
navigation.updateCurrentEntry({ state: newState });
console.log('تم تحديث الإعداد:', setting, 'إلى', value);
}
// مثال على الاستخدام:
updateUserSetting('theme', 'dark');
تقوم هذه الدالة باسترداد الحالة الحالية، وتدمج الإعداد المحدث، ثم تحدث إدخال السجل الحالي بالحالة الجديدة.
حالات الاستخدام المتقدمة والاعتبارات
1. التعامل مع عمليات إرسال النماذج
يمكن استخدام واجهة برمجة تطبيقات التنقل للتعامل مع عمليات إرسال النماذج في تطبيقات الصفحة الواحدة، مما يمنع إعادة تحميل الصفحة بالكامل ويوفر تجربة مستخدم أكثر سلاسة. يمكنك اعتراض حدث إرسال النموذج واستخدام `navigation.navigate()` لتحديث عنوان URL وعرض النتائج دون إعادة تحميل الصفحة بالكامل.
2. العمليات غير المتزامنة
عند التعامل مع أحداث التنقل، قد تحتاج إلى إجراء عمليات غير متزامنة، مثل جلب البيانات من واجهة برمجة تطبيقات. تتيح لك خاصية `event.transition` ربط وعد (promise) بحدث التنقل، مما يضمن أن ينتظر المتصفح حتى تكتمل العملية غير المتزامنة قبل تحديث الصفحة. انظر الأمثلة أعلاه.
3. استعادة موضع التمرير
يعد الحفاظ على موضع التمرير أثناء التنقل أمرًا بالغ الأهمية لتوفير تجربة مستخدم جيدة. توفر واجهة برمجة تطبيقات التنقل آليات لاستعادة موضع التمرير عند التنقل للخلف أو للأمام في سجل التصفح. يمكنك استخدام خاصية `scroll` الخاصة بـ `NavigationHistoryEntry` لتخزين واستعادة موضع التمرير.
4. معالجة الأخطاء
من الضروري معالجة الأخطاء التي قد تحدث أثناء التنقل، مثل أخطاء الشبكة أو الاستثناءات غير المعالجة. يتيح لك حدث `navigateerror` التقاط هذه الأخطاء ومعالجتها بأمان، مما يمنع تعطل التطبيق أو عرض رسالة خطأ للمستخدم.
5. التحسين التدريجي
عند بناء تطبيقات الصفحة الواحدة باستخدام واجهة برمجة تطبيقات التنقل، من المهم مراعاة التحسين التدريجي. تأكد من أن تطبيقك يعمل بشكل صحيح حتى لو لم تكن واجهة برمجة تطبيقات التنقل مدعومة من قبل المتصفح. يمكنك استخدام اكتشاف الميزات للتحقق من وجود كائن `navigation` والعودة إلى طرق التوجيه التقليدية إذا لزم الأمر.
مقارنة مع طرق التوجيه التقليدية
غالبًا ما تعتمد طرق التوجيه التقليدية في تطبيقات الصفحة الواحدة على التلاعب بكائن `window.location` أو استخدام مكتبات خارجية مثل `react-router` أو `vue-router`. في حين أن هذه الطرق مستخدمة على نطاق واسع وراسخة، إلا أن لها بعض القيود:
- إعادة تحميل الصفحة بالكامل: يمكن أن يؤدي التلاعب بـ `window.location` مباشرة إلى إعادة تحميل الصفحة بالكامل، مما قد يكون بطيئًا ومزعجًا لتجربة المستخدم.
- التعقيد: يمكن أن تكون إدارة سجل التصفح والحالة بالطرق التقليدية معقدة وعرضة للأخطاء، خاصة في التطبيقات الكبيرة والمعقدة.
- عبء الأداء: يمكن أن تضيف مكتبات التوجيه الخارجية عبئًا كبيرًا على الأداء، خاصة إذا لم يتم تحسينها للاحتياجات المحددة لتطبيقك.
تعالج واجهة برمجة تطبيقات التنقل هذه القيود من خلال توفير حل أكثر انسيابية وأداءً وغنيًا بالميزات للتوجيه وإدارة سجل التصفح. إنها تقضي على إعادة تحميل الصفحة بالكامل، وتبسط إدارة سجل التصفح، وتوفر تحكمًا دقيقًا في أحداث التنقل.
توافق المتصفحات
اعتبارًا من أواخر عام 2024، تتمتع واجهة برمجة تطبيقات التنقل بدعم جيد عبر المتصفحات الحديثة، بما في ذلك Chrome و Firefox و Safari و Edge. ومع ذلك، من الممارسات الجيدة دائمًا التحقق من أحدث معلومات توافق المتصفحات على مصادر مثل Can I use قبل تنفيذ واجهة برمجة تطبيقات التنقل في تطبيقات الإنتاج الخاصة بك. إذا كان دعم المتصفحات القديمة ضروريًا، ففكر في استخدام polyfill أو آلية احتياطية.
الخاتمة
تعد واجهة برمجة تطبيقات التنقل أداة قوية لبناء تطبيقات صفحة واحدة حديثة وعالية الأداء مع إمكانيات توجيه وإدارة سجل تصفح متقدمة. من خلال الاستفادة من ميزات الواجهة، يمكن للمطورين إنشاء تجارب مستخدم أسرع وأكثر سلاسة وجاذبية. في حين أن منحنى التعلم الأولي قد يكون أكثر حدة مقارنة باستخدام طرق أبسط وأقدم، فإن مزايا واجهة برمجة تطبيقات التنقل، خاصة في التطبيقات المعقدة، تجعلها استثمارًا جديرًا بالاهتمام. احتضن واجهة برمجة تطبيقات التنقل وأطلق العنان للإمكانات الكاملة لتطبيقات الصفحة الواحدة الخاصة بك.